package com.lagou.edu.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.jwt.crypto.sign.MacSigner;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

/**
 * @author renpeiqian
 * 资源服务器 oauth配置
 * @date 2021/7/23 16:00
 * @since
 */
@Configuration
@EnableResourceServer  //开启资源服务器功能
@EnableWebSecurity    //开启web访问安全
public class ResourceServerConfig  extends ResourceServerConfigurerAdapter {

    @Value("oauth.remote.check_url")
    private String check_url;

    private String SIGN_KEY = "Hik123";

    /**
     * @Description 定于资源服务器向远程认证服务器发送请求（oauth/check），进行token校验等
     * @Param [resources]
     * @return void
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

//        //设置当前资源服务器id，与认证服务器的id要匹配一致
//        resources.resourceId("autodeliver");
//        //定义token服务对象（token校验需要依据token服务对象）
//        RemoteTokenServices remoteTokenServices= new RemoteTokenServices();
//
//        //设置认证服务器校验token接口
//        remoteTokenServices.setCheckTokenEndpointUrl("http://127.0.0.1:9999/oauth/check_token");
//        //设置客户端id、安全码
//        remoteTokenServices.setClientId("client_lagou");
//        remoteTokenServices.setClientSecret("123456");
//
//        resources.tokenServices(remoteTokenServices);

        //配置jwt令牌
        resources
                //设置资源id
                .resourceId("autodeliver")
                //设置token的存储方式
                .tokenStore(tokenStore())
                //无状态设置
                .stateless(true);

    }

    /**
     * @Description 定义接口开放细节
     * 资源服务器有较多资源（资源其实在这里理解为接口）
     * 我们定义接口的开放规则，有些需要开放，有些必须经过验证才能访问。
     * 具体策略可以通过该方法进行配置
     * @Param [http]
     * @return void
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                //设置session的创建策略
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .and()
                .authorizeRequests()
                //需要进行验证的url
                .antMatchers("/autodeliver/**").authenticated()
                .antMatchers("/oauth/**").authenticated()
                //其他的请求都可以放行。即不需要验证
                .anyRequest().permitAll();

    }

    /**
     * @Description :配置token的存储方式
     * InMemoryTokenStore ：存储在内存中，方便开发调试。
     * JdbcTokenStore ：基于JDBC的实现版本，令牌（Token）会被保存在数据库中。
     * JwtTokenStore ：将令牌相关的数据进⾏编码，后端服务不需要存储。
     * @Param
     * @return
     */
    public TokenStore tokenStore(){

        //return  new InMemoryTokenStore();

        //使用jwt进行存储令牌
        return new JwtTokenStore(jwtAccessTokenConverter());
    }


    /**
     * @Description: jwt令牌转换器
     * 可以再次将secret签名密钥进行配置。
     * @Param []
     * @return org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
     */
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        //配置签名密钥
        jwtAccessTokenConverter.setSigningKey(SIGN_KEY);

        //验证时使用的密钥，和签名密钥保持一致
        jwtAccessTokenConverter.setVerifier(new MacSigner(SIGN_KEY));

        return jwtAccessTokenConverter;

    }
}
